/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2018年11月22日
 * V4.0
 */
package com.jphenix.share.tools;

import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import com.jphenix.standard.docs.ClassInfo;

/**
 * 3DES加解密处理类
 * 
 * 2018-11-29 增加了加密后做Base64，支持RF2405标准的编码字符串（带回车的）
 * 
 * @author MBG
 * 2018年11月22日
 */
@ClassInfo({"2020-07-17 13:51","读取配置文件的静态类"})
public class Desede {

	private boolean outRf2405    = false;                    //输出的Base64编码格式，是否按照RF2405标准
    private String secretKey     = "jphenix_3des_secretkey"; //密钥
    private String secretType    = "ECB";                    //加解密类型ECB,CBC,CTR,OFB,CFB
    private String secretPadding = "PKCS5Padding";           //填充类型PKCS1Padding,PKCS5Padding,SSL3Padding,OAEPPadding,ISO10126Padding,NoPadding,PKCS7Padding
    private String encoding      = "utf-8";                  //加解密统一使用的编码方式  
	
	/**
	 * 构造函数
	 * @author MBG
	 */
	public Desede() {
		super();
	}

	/**
	 * 构造函数
	 * @param secretKey        密钥
	 * @param secretType       加解密类型
	 * @param secretPadding    填充类型
	 * @param encoding         加解密统一使用的编码方式  
	 * @author MBG
	 */
	public Desede(String secretKey,String secretType,String secretPadding,String encoding) {
		super();
		if(secretKey!=null && secretKey.length()>0) {
			this.secretKey = secretKey;
		}
		if(secretType!=null && secretType.length()>0) {
			this.secretType = secretType;
		}
		if(secretPadding!=null && secretPadding.length()>0) {
			this.secretPadding = secretPadding;
		}
		if(encoding!=null && encoding.length()>0) {
			this.encoding = encoding;
		}
	}
	
	
	/**
	 * 执行加密
	 * @param plainText    需要加密的字符串
	 * @param secretKey    密钥
	 * @return             加密后的字符串
	 * @throws Exception   异常
	 * 2018年11月22日
	 * @author MBG
	 */
	public static String enc(String plainText,String secretKey) throws Exception {
		return (new Desede(secretKey,null,null,null)).encode(plainText);
	}


	/**
	 * 执行加密 返回RF2405标准的密文（在做Base64加密时，带换行字符）
	 * @param plainText    需要加密的字符串
	 * @param secretKey    密钥
	 * @return             加密后的字符串
	 * @throws Exception   异常
	 * 2018年11月22日
	 * @author MBG
	 */
	public static String rf2405Enc(String plainText,String secretKey) throws Exception {
		return (new Desede(secretKey,null,null,null)).setOutRf2405(true).encode(plainText);
	}
	
	/**
	 * 执行加密
	 * @param plainText   需要加密的字符串
	 * @return            加密后的字符串
	 * @throws Exception  异常
	 * 2018年11月22日
	 * @author MBG
	 */
	public static String enc(String plainText) throws Exception {
		return (new Desede()).encode(plainText);
	}
	
	/**
	 * 执行解密
	 * @param encryptText  需要解密的字符串
	 * @param secretKey    密钥
	 * @return             解密后的字符串
	 * @throws Exception   异常
	 * 2018年11月22日
	 * @author MBG
	 */
	public static String dec(String encryptText,String secretKey) throws Exception {
		return (new Desede(secretKey,null,null,null)).decode(encryptText);
	}
	
	/**
	 * 执行解密
	 * @param encryptText  需要解密的报文
	 * @return             解密后的报文
	 * @throws Exception   异常
	 * 2018年11月22日
	 * @author MBG
	 */
	public static String dec(String encryptText) throws Exception {
		return (new Desede()).decode(encryptText);
	}
	
    /**
     * 3DES加密
     *
     * @param plainText   普通文本
     * @return            加密后的报文
     * @throws Exception  异常
     */
    public String encode(String plainText) throws Exception {
        DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        Key deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede/"+secretType+"/"+secretPadding);
        cipher.init(Cipher.ENCRYPT_MODE, deskey);
        byte[] oBytes = cipher.doFinal(plainText.getBytes(encoding));
        if(outRf2405) {
        	return Base64.rfc2405Encode(oBytes);
        }
        return Base64.base64Encode(oBytes);
    }
    
    /**
     * 3DES解密
     * @param encryptText 加密内容
     * @return            解密后的内容
     * @throws Exception  异常
     */
    public String decode(String encryptText) throws Exception {
        DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        Key deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede/"+secretType+"/"+secretPadding);
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        return new String(cipher.doFinal(Base64.decode64(encryptText)), encoding);
    }
    
	/**
	 * 设置加解密密钥
	 * @param key 加解密密钥
	 * 2018年11月22日
	 * @author MBG
	 */
	public void setSecretKey(String key) {
		secretKey = key;
	}
	
	/**
	 * 设置编码格式
	 * @param enc 编码格式
	 * 2018年11月22日
	 * @author MBG
	 */
	public void setEncoding(String enc) {
		encoding = enc;
	}
	
	/**
	 * 设置填充方式
	 * @param padding 填充方式
	 * PKCS1Padding,PKCS5Padding,SSL3Padding,OAEPPadding
	 * ,ISO10126Padding,NoPadding,PKCS7Padding
	 * 2018年11月22日
	 * @author MBG
	 */
	public void setSecretPadding(String padding) {
		secretPadding = padding;
	}
	
	/**
	 * 设置加密类型
	 * @param type 加密类型 ECB,CBC,CTR,OFB,CFB
	 * 2018年11月22日
	 * @author MBG
	 */
	public void setSecretType(String type) {
		secretType = type;
	}
	
	/**
	 * 设置输出的Base64编码格式，是否按照RF2405标准
	 * @param enabled 输出的Base64编码格式，是否按照RF2405标准
	 * @return 当前类实例
	 * 2018年11月29日
	 * @author MBG
	 */
	public Desede setOutRf2405(boolean enabled) {
		outRf2405 = enabled;
		return this;
	}
}
